package com.linkoog.devtools.code_generator.setting.configurable.ui.template;

import com.linkoog.devtools.code_generator.template.model.ContainerNodeData;
import com.linkoog.devtools.code_generator.template.model.NodeData;
import com.linkoog.devtools.code_generator.template.model.NodeDataFactory;
import com.linkoog.devtools.code_generator.template.model.node.FileNodeData;
import com.linkoog.devtools.code_generator.template.model.node.DirNodeData;
import com.linkoog.devtools.code_generator.template.model.node.TemplateNodeData;
import com.linkoog.devtools.code_generator.setting.configurable.ui.TemplateSettingPanel;
import com.linkoog.devtools.code_generator.setting.persistent.CodeGenDevToolsPersistent;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.ui.Messages;
import com.intellij.ui.ToolbarDecorator;
import com.intellij.ui.treeStructure.Tree;
import com.intellij.util.ui.JBUI;

import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.List;

public class TemplateLeftPanelBuilder {

    private static final Logger LOGGER = Logger.getInstance(TemplateLeftPanelBuilder.class);

    private final TemplateSettingPanel templateSettingPanel;

    JPanel myMainPanel;
    JTree templateTree;
    ToolbarDecorator toolbarDecorator;

    public TemplateLeftPanelBuilder(TemplateSettingPanel templateSettingPanel){
        this.templateSettingPanel = templateSettingPanel;

        initTemplateTree();
        initToolbarDecorator();

        myMainPanel = toolbarDecorator.createPanel();
        myMainPanel.setPreferredSize(JBUI.size(240,100));
    }

    public JPanel getMyMainPanel() {
        return myMainPanel;
    }

    public JTree getTemplateTree() {
        return templateTree;
    }

    public ToolbarDecorator getToolbarDecorator() {
        return toolbarDecorator;
    }


    private void initToolbarDecorator(){
        toolbarDecorator = ToolbarDecorator.createDecorator(templateTree);
        toolbarDecorator.setAddAction(anActionButton -> {
            insertTemplateNode(NodeDataFactory.createTemplateNodeData());
        });

    }



    private void setSelectTreeNode(DefaultMutableTreeNode treeNode){
        templateTree.setSelectionPath(new TreePath(treeNode.getPath()));
    }

    private void startEditingTreeNode(DefaultMutableTreeNode treeNode){
        templateTree.setEditable(true);
        templateTree.startEditingAtPath(new TreePath(treeNode.getPath()));
    }



    private void initTemplateTree(){
        templateTree = new Tree();
        templateTree.putClientProperty("JTree.lineStyle", "Horizontal");
        templateTree.setRootVisible(false);
        templateTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
        templateTree.setCellRenderer(new TemplateTreeCellRenderer());
        templateTree.setEditable(false);
        templateTree.setCellEditor(new TemplateTreeCellEditor(templateTree));


        //节点选择事件
        /*templateTree.addTreeSelectionListener( it -> {
            DefaultMutableTreeNode node = (DefaultMutableTreeNode) templateTree.getLastSelectedPathComponent();
            if (node == null) {
                return;
            }
            Object object = node.getUserObject();
            if(object instanceof TemplateNodeData) {
                TemplateNodeData templateNodeData = (TemplateNodeData) object;
                templateSettingPanel.showTemplateRootPanel(templateNodeData);
            } else {
            }
        });*/

        DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode();
        DefaultTreeModel model = new DefaultTreeModel(rootNode);


        List<TemplateNodeData> templateNodeDataList = CodeGenDevToolsPersistent.getInstance().getTemplateDataList();
        for (TemplateNodeData templateNodeData : templateNodeDataList) {
            rootNode.add(buildTemplateNode(templateNodeData.deepCopy()));
        }


        templateTree.setModel(model);

        //templateTree.addMouseListener(new MyTreePopupMenuActionListener());

        //初始化右键菜单
        JPopupMenu rootNodePopupMenu = createRootNodePopupMenu(templateTree);
        JPopupMenu packageNodePopupMenu = createPackageNodePopupMenu(templateTree);
        JPopupMenu fileNodePopupMenu = createFileNodePopupMenu(templateTree);
        templateTree.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                int row = templateTree.getRowForLocation(e.getX(), e.getY());
                templateTree.setSelectionRow(row);
                if (row == -1) {
                    templateSettingPanel.showLeftContextPanel(null);
                    return;
                }

                templateTree.setSelectionRow(row);
                DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) templateTree.getLastSelectedPathComponent();

                Object selectedNodeObject = selectedNode.getUserObject();
                if (selectedNodeObject == null) {
                    return;
                }


                if (SwingUtilities.isLeftMouseButton(e)) {
                    if (!isDoubleClick(e)) {
                        //鼠标左键--单击
                        if (selectedNodeObject instanceof TemplateNodeData) {
                            TemplateNodeData templateNodeData = (TemplateNodeData) selectedNodeObject;
                            templateSettingPanel.showLeftContextPanel(templateNodeData);
                        }else if(selectedNodeObject instanceof DirNodeData) {
                            DirNodeData dirNodeData = (DirNodeData) selectedNodeObject;
                            templateSettingPanel.showLeftContextPanel(dirNodeData);

                        } else if (selectedNodeObject instanceof FileNodeData) {
                            //选中的节点,为rest接口
                            FileNodeData fileNodeData = (FileNodeData) selectedNodeObject;
                            templateSettingPanel.showLeftContextPanel(fileNodeData);
                        }
                    } else {
                        //鼠标左键--双击
                        if (selectedNodeObject instanceof TemplateNodeData) {
                            TemplateNodeData templateNodeData = (TemplateNodeData) selectedNodeObject;
                            //startEditingTreeNode(selectedNode);
                        } else if (selectedNodeObject instanceof DirNodeData) {
                            DirNodeData dirNodeData = (DirNodeData) selectedNodeObject;
                            //startEditingTreeNode(selectedNode);
                        } else if (selectedNodeObject instanceof FileNodeData) {
                            FileNodeData fileNodeData = (FileNodeData) selectedNodeObject;
                            //startEditingTreeNode(selectedNode);
                        }
                    }
                }else if (SwingUtilities.isRightMouseButton(e)) {
                    //鼠标右键--显示菜单
                    if (selectedNodeObject instanceof TemplateNodeData) {
                        //root节点
                        rootNodePopupMenu.show(e.getComponent(), e.getX(), e.getY());
                    }else if (selectedNodeObject instanceof DirNodeData) {
                        //package节点
                        packageNodePopupMenu.show(e.getComponent(), e.getX(), e.getY());
                    } else if (selectedNodeObject instanceof FileNodeData) {
                        //file节点
                        fileNodePopupMenu.show(e.getComponent(), e.getX(), e.getY());
                    }
                }
            }
        });
    }


    private DefaultMutableTreeNode buildTemplateNode(TemplateNodeData templateNodeData){
        DefaultMutableTreeNode treeNode = new DefaultMutableTreeNode(templateNodeData);
        List<NodeData> nodeDataList = templateNodeData.getChildNodeList();
        for (NodeData nodeData : nodeDataList) {
            addChildNode(treeNode, nodeData);
        }
        return treeNode;
    }

    private void addChildNode(DefaultMutableTreeNode parentNode, NodeData nodeData){
        DefaultMutableTreeNode node = new DefaultMutableTreeNode(nodeData);
        parentNode.add(node);
        if (nodeData instanceof ContainerNodeData){
            ContainerNodeData containerNodeData = (ContainerNodeData)nodeData;
            for (NodeData data : containerNodeData.getChildNodeList()) {
                addChildNode(node, data);
            }
        } else if (nodeData instanceof FileNodeData){
            return;
        }
    }




    /**
     * rootNode节点的右键菜单
     */
    private JPopupMenu createRootNodePopupMenu(JTree jTree) {
        JPopupMenu popupMenu = new JPopupMenu();

        JMenuItem renameAction = new JMenuItem("重命名");
        popupMenu.add(renameAction);
        renameAction.addActionListener(e -> {
            DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) jTree.getLastSelectedPathComponent();
            startEditingTreeNode(selectedNode);
        });

        JMenuItem addPackageAction = new JMenuItem("添加目录");
        popupMenu.add(addPackageAction);
        addPackageAction.addActionListener(e -> {
            DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) jTree.getLastSelectedPathComponent();
            TemplateNodeData templateNodeData = (TemplateNodeData)selectedNode.getUserObject();
            insertPackageNode(selectedNode, NodeDataFactory.createPackageNodeData(templateNodeData));
        });

        JMenuItem addFileAction = new JMenuItem("添加文件");
        popupMenu.add(addFileAction);
        addFileAction.addActionListener(e -> {
            DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) jTree.getLastSelectedPathComponent();
            TemplateNodeData templateNodeData = (TemplateNodeData)selectedNode.getUserObject();
            insertFileNode(selectedNode, NodeDataFactory.createFileNodeData(templateNodeData));
        });

        JMenuItem deleteAction = new JMenuItem("删除");
        popupMenu.add(deleteAction);
        deleteAction.addActionListener(e -> {
            DefaultTreeModel defaultTreeModel = (DefaultTreeModel) jTree.getModel();
            DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) jTree.getLastSelectedPathComponent();
            if (selectedNode.isRoot()) {
                return;
            }

            int result = Messages.showYesNoDialog("是否删除该模板", "确认删除？", Messages.getQuestionIcon());
            if (result == Messages.YES) {
                defaultTreeModel.removeNodeFromParent(selectedNode);
            }
        });

        return popupMenu;
    }

    /**
     * packageNode节点的右键菜单
     */
    private JPopupMenu createPackageNodePopupMenu(JTree jTree) {
        JPopupMenu popupMenu = new JPopupMenu();

        JMenuItem renameAction = new JMenuItem("重命名");
        popupMenu.add(renameAction);
        renameAction.addActionListener(e -> {
            DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) jTree.getLastSelectedPathComponent();
            startEditingTreeNode(selectedNode);
        });



        JMenuItem addPackageAction = new JMenuItem("添加目录");
        popupMenu.add(addPackageAction);
        addPackageAction.addActionListener(e -> {
            DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) jTree.getLastSelectedPathComponent();
            DirNodeData dirNodeData = (DirNodeData)selectedNode.getUserObject();
            insertPackageNode(selectedNode, NodeDataFactory.createPackageNodeData(dirNodeData));
        });

        JMenuItem addFileAction = new JMenuItem("添加文件");
        popupMenu.add(addFileAction);
        addFileAction.addActionListener(e -> {
            DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) jTree.getLastSelectedPathComponent();
            DirNodeData dirNodeData = (DirNodeData)selectedNode.getUserObject();
            insertFileNode(selectedNode, NodeDataFactory.createFileNodeData(dirNodeData));
        });


        JMenuItem deleteAction = new JMenuItem("删除");
        popupMenu.add(deleteAction);
        deleteAction.addActionListener(e -> {
            DefaultTreeModel defaultTreeModel = (DefaultTreeModel) jTree.getModel();
            DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) jTree.getLastSelectedPathComponent();
            if (selectedNode.isRoot()) {
                return;
            }

            int result = Messages.showYesNoDialog("是否删除该文件夹和下面的全部内容", "确认删除？", Messages.getQuestionIcon());
            if (result == Messages.YES) {
                DefaultMutableTreeNode parentNode =  (DefaultMutableTreeNode)selectedNode.getParent();
                ContainerNodeData parentContainerNodeData = (ContainerNodeData)parentNode.getUserObject();
                parentContainerNodeData.removeChildNode((NodeData)selectedNode.getUserObject());
                defaultTreeModel.removeNodeFromParent(selectedNode);
            }
        });

        return popupMenu;
    }

    /**
     * fileNode节点的右键菜单
     */
    private JPopupMenu createFileNodePopupMenu(JTree jTree) {
        JPopupMenu popupMenu = new JPopupMenu();

        JMenuItem renameAction = new JMenuItem("重命名");
        popupMenu.add(renameAction);
        renameAction.addActionListener(e -> {
            DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) jTree.getLastSelectedPathComponent();
            startEditingTreeNode(selectedNode);
        });

        JMenuItem deleteAction = new JMenuItem("删除");
        popupMenu.add(deleteAction);
        deleteAction.addActionListener(e -> {
            DefaultTreeModel defaultTreeModel = (DefaultTreeModel) jTree.getModel();
            DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) jTree.getLastSelectedPathComponent();
            if (selectedNode.isRoot()) {
                return;
            }

            int result = Messages.showYesNoDialog("是否删除该模板文件", "确认删除？", Messages.getQuestionIcon());
            if (result == Messages.YES) {
                DefaultMutableTreeNode parentNode =  (DefaultMutableTreeNode)selectedNode.getParent();
                ContainerNodeData parentContainerNodeData = (ContainerNodeData)parentNode.getUserObject();
                parentContainerNodeData.removeChildNode((NodeData)selectedNode.getUserObject());
                defaultTreeModel.removeNodeFromParent(selectedNode);
            }
        });

        return popupMenu;
    }

    private void insertChildNode(DefaultMutableTreeNode parentNode){
        final Object parentNodeDataObject = parentNode.getUserObject();
        if (parentNodeDataObject instanceof ContainerNodeData) {
            ContainerNodeData parentContainerNodeData = (ContainerNodeData) parentNodeDataObject;

            List<NodeData> nodeDataList = parentContainerNodeData.getChildNodeList();
            for (NodeData nodeData : nodeDataList){
                DefaultMutableTreeNode childTreeNode = new DefaultMutableTreeNode(nodeData);
                parentNode.add(childTreeNode);
                if (nodeData instanceof ContainerNodeData){
                    insertChildNode(childTreeNode);
                }
            }
        }
    }

    public void insertTemplateNode(TemplateNodeData templateNodeData){
        DefaultTreeModel model = (DefaultTreeModel) templateTree.getModel();
        DefaultMutableTreeNode root = (DefaultMutableTreeNode)model.getRoot();

        DefaultMutableTreeNode templateNode = new DefaultMutableTreeNode(templateNodeData);
        insertChildNode(templateNode);
        model.insertNodeInto(templateNode, root, root.getChildCount());

        setSelectTreeNode(templateNode);
        startEditingTreeNode(templateNode);
    }


    private void insertPackageNode(DefaultMutableTreeNode parentNode, DirNodeData packageNode){
        final Object parentNodeDataObject = parentNode.getUserObject();
        if (parentNodeDataObject instanceof ContainerNodeData) {
            //ContainerNodeData parentContainerNodeData = (ContainerNodeData) parentNodeDataObject;
            //parentContainerNodeData.addChildNode(packageNode);

            DefaultTreeModel model = (DefaultTreeModel) templateTree.getModel();
            DefaultMutableTreeNode treeNode = new DefaultMutableTreeNode(packageNode);
            insertChildNode(treeNode);
            model.insertNodeInto(treeNode, parentNode, parentNode.getChildCount());

            setSelectTreeNode(treeNode);
            startEditingTreeNode(treeNode);
        }
    }

    private void insertFileNode(DefaultMutableTreeNode parentNode, FileNodeData fileNodeData){
        final Object parentNodeDataObject = parentNode.getUserObject();
        if (parentNodeDataObject instanceof ContainerNodeData) {
            //ContainerNodeData parentContainerNodeData = (ContainerNodeData) parentNodeDataObject;
            //parentContainerNodeData.addChildNode(fileNodeData);

            DefaultTreeModel model = (DefaultTreeModel) templateTree.getModel();
            DefaultMutableTreeNode treeNode = new DefaultMutableTreeNode(fileNodeData);
            model.insertNodeInto(treeNode, parentNode, parentNode.getChildCount());

            setSelectTreeNode(treeNode);
            startEditingTreeNode(treeNode);
        }
    }

    public static boolean isDoubleClick(MouseEvent e) {
        return e != null && e.getClickCount() > 0 && e.getClickCount() % 2 == 0;
    }








}
